import "reflect-metadata";
import { DataSource } from "typeorm";
import { SMTPServer } from "smtp-server";
import * as mailparser from "mailparser";
import { Issue } from "./entity/newsletter";
import * as http from "http";

const port = 4041;
const emailUrl = "smtp://localhost:2525";

function nowTime() {
  return Math.floor(new Date().getTime() / 1000);
}

const appData = new DataSource({
  type: "sqlite",
  database: "newsletter.db",
  entities: [Issue],
  synchronize: true,
  logging: false,
});

const issueRep = appData.getRepository(Issue);

const emailApplication = new SMTPServer({
  disabledCommands: ["AUTH", "STARTTLS"],
  async onData(stream, session, callback) {
    try {
      const email = await mailparser.simpleParser(stream);
      const from = email.from?.text ?? "";
      const subject = email.subject ?? "";
      const body =
        typeof email.html === "string" ? email.html : email.textAsHtml ?? "";
      for (const address of new Set(
        session.envelope.rcptTo.map(
          (smtpServerAddress) => smtpServerAddress.address
        )
      )) {
        const addressParts = (address as string).split("@");
        if (addressParts.length !== 2) continue;
        const issue = new Issue();
        issue.titile = subject;
        issue.author = from;
        issue.content = body;
        issue.createdAt = nowTime();
        console.log("保存邮件: ", issue);
        await issueRep.save(issue);
      }
      callback();
    } catch (error) {
      console.error(
        `Failed to receive message: ‘${JSON.stringify(session, null, 2)}’`
      );
      console.error(error);
      stream.resume();
      callback(new Error("Failed to receive message. Please try again."));
    }
  },
});

// 使用 typeorm 连接数据库
appData
  .initialize()
  .then(async () => {
    emailApplication.listen(new URL(emailUrl).port, () => {
      console.log(`Email server started at ${emailUrl}`);
    });
    http
      .createServer(async function (request, response) {
        response.writeHead(200, { "Content-Type": "text/plain" });
        const issues = await issueRep.find({ take: 6 });
        response.end(JSON.stringify(issues));
      })
      .listen(port);

      console.log(`App server started at ${port}`);
  })
  .catch((error) => console.log("TypeORM connection OR App error: ", error));
